Optional
Atem provides null safety by providing language built-in optional types.
The question mark symbolizes the optional type, you can convert types to optional types by putting a question mark in front of them, like:
optional_int mutable: ?i8 = 12;
optional_int = null;
Now the variable optional_int
could be an i8
or null
.
Optional Types
You can create optional type by putting a ?
in front of the type:
opt_int mutable: ?i8 = 12;
To access the child type of an optional type, use compile-time reflection:
assert(^opt_int.getType().getChildType() == i8);
You can initialize or assign null
to an optional to mean the optional is "empty":
opt_int = null;
To use the value of the optional, you need to unwrap it:
int1 := opt_int ?? -1; //the int1 would be -1 when the opt_int is null
int2 := try opt_int.?; //will throw an UnwrappingException when the opt_int is null
int3 := opt_int.!; //will terminate program at runtime or terminate compilation at compile-time
If the child type of an optional has members, the optional chaining operator !.
and ?.
will be used to access them:
blog : struct = {
id: u8;
name: string;
checkBlogValidity: () -> bool func {...};
};
blog_opt: ?blog = .{id = 3, name = "std-atem"};
id := try blog_opt?.id;
//equivalent to:
id := try blog_opt.?.id;
name := blog_opt!.name; //will terminate program at runtime or terminate compilation at compile-time
//equivalent to:
name := blog_opt.!.name;
Optional Pointers
The normal pointers in Atem couldn't be null. If you want a pointer to be nullable, use optional pointer instead:
ptr mutable: i8.& = null; //compile error
opt_ptr mutable: ?i8.& = null; //good
The optional pointer is guaranteed to be the same size of the child pointer type:
assert(^opt_ptr.getType().size() == ^i8.&.size());